package messages;

import Messages.Exceptions.MessageCreationException;
import Messages.Exceptions.MessageLengthException;
import Model.FileId;
import Model.PathFile;
import Model.Status;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.UnknownHostException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @author Groupe RT-A1
 */
/**
 * Utilisee pour gerer la creation de messages
 */
public class MessagesFactory {

        private MessagesFactory() {}
        
    /**
    * Renvoie un byte[] contenant un signal Hello 
    * @param login     Login de l'utilisateur local
    * @param waitAck   Type de la requete Hello
    *                  <code>true</code> si Hello Request 
    *                  <code>false</code> si Hello Reply
    * @throws MessageCreationException
    * @return byte[] 
    */
    public static byte[] getHello(String login, boolean waitAck) throws MessageCreationException {
        Hello myHello;
        try {
            myHello = new Hello(login, waitAck);
            return createByte(myHello).toByteArray();

        } catch (UnknownHostException e) {
            throw new MessageCreationException("Impossible de déterminer votre nom d'hôte",e);

        } catch (IOException e) {
            throw new MessageCreationException("Impossible de créer le byte[]",e);
        }
    }      
    /**
    * Renvoie le byte[] contenant un signal ChatMessage 
    * @param login     Login de l'utilisateur local
    * @param msgToSend Message texte à envoyer
    * @throws MessageCreationException
    * @throws MessageLengthException
    * @return byte[] 
    */
    public static byte[] getChatMessage(String login, String msgToSend) throws MessageCreationException,MessageLengthException {
        ChatMessage myMessage;
        try {
            myMessage = new ChatMessage(login, msgToSend);
            return createByte(myMessage).toByteArray();
        } catch (MessageLengthException ex) {
            Logger.getLogger(MessagesFactory.class.getName()).log(Level.SEVERE, null, ex);
            throw new MessageLengthException("Message non conforme",ex);
        } catch (UnknownHostException e) {
            throw new MessageCreationException("Impossible de déterminer votre nom d'hôte",e);
        }
        catch (IOException e) {
            throw new MessageCreationException("Impossible de créer le byte[]",e);
        }
    }
    /**
    * Renvoie le byte [] contenant un signal Bye
    * @param login Login de l'utilisateur local en cours de deconnexion
    * @throws MessageCreationException
    * @return byte[] 
    */
    public static byte[] getBye(String login) throws MessageCreationException {
        Bye myBye;
        try {
            myBye = new Bye(login);
            return createByte(myBye).toByteArray();
        } catch (UnknownHostException e) {
            throw new MessageCreationException("Impossible de déterminer votre nom d'hôte",e);
        }
        catch (IOException e) {
            throw new MessageCreationException("Impossible de créer le byte[]",e);
        }  
    }      
    /**
    * Renvoie le byte[] contenant un signal FileRequest 
    * @param  login     Login de l'utilisateur local
    * @param  path      PathFile du fichier à transferer 
    * @param  fileId    FileID du fichier à transferer
    * @param  size      Taille du fichier à transferer
    * @throws MessageCreationException
    * @return byte[]
    */
    public static byte[] getFileRequest(String login, PathFile path , FileId fileId, long size) throws MessageCreationException {
        FileRequest myRequest;
        try {
            myRequest = new FileRequest(login, path, fileId, size);
            return createByte(myRequest).toByteArray();       
        } catch (UnknownHostException e) {
            throw new MessageCreationException("Impossible de déterminer votre nom d'hôte",e);
        }
        catch (IOException e) {
            throw new MessageCreationException("Impossible de créer le byte[]",e);
        }     
    }

    /**
    * Renvoie le byte [] contenant un signal Wizz
    * @param login
    * @throws MessageCreationException
    * @return byte[]
    */
    public static byte[] getWizz(String login) throws MessageCreationException {
        Wizz myWizz;
        try {
            myWizz = new Wizz(login);
            return createByte(myWizz).toByteArray();       
        } catch (UnknownHostException e) {
            throw new MessageCreationException("Impossible de déterminer votre nom d'hôte",e);
        }
        catch (IOException e) {
            throw new MessageCreationException("Impossible de créer le byte[]",e);
        }  
    }   
    /**
    * Renvoie le byte[] contenant un signal FileResponse 
    * @param  login     Login de l'utilisateur local
    * @param  accept    Reponse à la demande de transfert
    *                   <code>true</code> si accepté 
    *                   <code>false</code> sinon 
    * @param  portReception   Port de reception pour le transfert de fichier
    * @param  fileid          Identifiant du fichier accepté
    * @throws UnknownHostException  
    * @return byte[]
    */
    public static byte[] getFileResponse(String login, boolean accept ,int portReception, FileId fileid) throws MessageCreationException {
        FileResponse myResponse;
        try {
            myResponse = new FileResponse(login, accept, portReception, fileid);
            return createByte(myResponse).toByteArray();       
        } catch (UnknownHostException e) {
            throw new MessageCreationException("Impossible de déterminer votre nom d'hôte",e);
        }
        catch (IOException e) {
            throw new MessageCreationException("Impossible de créer le byte[]",e);
        }     
    }
    /**
    * Renvoie le byte[] contenant un signal Presence 
    * @param  login     Login de l'utilisateur local
    * @param  show      Status de l'utilisateur à notifier
    * @throws MessageCreationException
    * @return byte[]
    */
    public static byte[] getPresence(String login, Status show) throws MessageCreationException {
        Presence myStatus;
        try {
            myStatus = new Presence(login,show);
            return createByte(myStatus).toByteArray();       
        } catch (UnknownHostException e) {
            throw new MessageCreationException("Impossible de déterminer votre nom d'hôte",e);
        }
        catch (IOException e) {
            throw new MessageCreationException("Impossible de créer le byte[]",e);
        }     
    }
     /**
    * Renvoie le byte[] contenant un signal Composing 
    * @param login Login de l'utilisateur local
    * @param isWriting   <code>true</code> si utilisateur ecrit 
    *                  <code>false</code> sinon
    * @throws MessageCreationException
    * @return byte[]
    */
    public static byte[] getComposing(String login,boolean isWriting) throws MessageCreationException {
        Composing myComposing;
        try {
            myComposing = new Composing(login,isWriting);
            return createByte(myComposing).toByteArray();       
        } catch (UnknownHostException e) {
            throw new MessageCreationException("Impossible de déterminer votre nom d'hôte",e);
        }
        catch (IOException e) {
            throw new MessageCreationException("Impossible de créer le byte[]",e);
        }     
    }
    /**
    * Renvoie le message correspondant au byte[] passe en argument
    * @param myArray 
    * @return Message
    * @throws MessageCreationException
    */
    public static Message getMessage(byte[] myArray) throws MessageCreationException {
        ByteArrayInputStream byteAIS;
        ObjectInputStream ois;
        try {

            byteAIS = new ByteArrayInputStream(myArray);
            ois = new ObjectInputStream(byteAIS);
            Object monObject = ois.readObject();

            if (monObject instanceof Message) {
                    return (Message)monObject;
            }
            else {
                    throw new MessageCreationException("Le Byte[] ne correspond pas à un message connu");
            }

        } catch (IOException e) {
            throw new MessageCreationException("Impossible de créer le message",e);

        } catch (ClassNotFoundException e) {
            throw new MessageCreationException("Impossible de créer le message",e);
        } 
    }
    /**
    * Renvoie un ByteArrayOutputStream contenant le message myMessage
    * @param myMessage
    * @return ByteArrayOutputStream
    * @throws IOException
    */
    private static ByteArrayOutputStream createByte(Message myMessage) throws IOException {
        ByteArrayOutputStream byteAOS;
        ObjectOutputStream oos;

        byteAOS = new ByteArrayOutputStream();

        oos = new ObjectOutputStream(byteAOS);
        oos.writeObject(myMessage);
        oos.flush();
        oos.close();

        return byteAOS;
    }   
}